// 四个promise封装的异步动作，其中三个返回resolve，一个返回reject
function asyncAction1() {
  let p = new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve('1');
    }, 3000);
  });
  return p;
}

function asyncAction2() {
  let p = new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve('2');
    }, 2000);
  });
  return p;
}

function asyncAction3() {
  let p = new Promise(function(resolve, reject) {
    setTimeout(function() {
      resolve('3');
    }, 1000);
  });
  return p;
}

function asyncAction4() {
  let p = new Promise(function(resolve, reject) {
    setTimeout(function() {
      reject('error');
    }, 4000);
  });
  return p;
}

// promise.all返回数据的顺序和参数列表申明顺序相同，与异步完成时间无关。
// 尽管返回数据时，是按顺序的，但是执行时，所有promise都是并行的，promise.all在所有promise都fullfilled的情况下，完成时间以最晚fullfilled的promise为准。

console.log(new Date());
promiseArr = [asyncAction1(), asyncAction2(), asyncAction3()];
Promise.all(promiseArr).then(res => {
  console.log(res);
  console.log(new Date());
});

// promise.all也只返回一个promise，所以当遇到第一个rejected的promise时，就会立即返回rejected，其他fullfilled的promise即使执行了也不会返回。
promiseArr = [asyncAction1(), asyncAction2(), asyncAction3(), asyncAction4()];
Promise.all(promiseArr)
  .then(res => {
    console.log(res);
  })
  .catch(err => {
    console.log(err);
  });

// 有时候,我们使用Promise.all同时发起若干异步请求，但并不希望因为一个失败而放弃其余请求，此时我们可以对promise队列进行改动，最终使得rejected信息也以fullfilled的状态输出。

// 当catch捕获rejected信息后，promise的链条就恢复了，我们可以在catch中将错误信息进行返回，那么下一步then返回的promise将会成为fufilled状态,错误信息将成为resolve回调函数的参数。
asyncAction4()
  .catch(err => {
    return err;
  })
  .then(res => {
    console.log(res);
  });

// 因此我们可以通过map方法对promiseArr中返回rejected状态的promise进行上述处理，保证promise.all始终能够完成，而错误信息也出现在resolve回调函数的参数数组中。
Promise.all(promiseArr.map(p => p.catch(err => err)))
  .then(res => {
    console.log(res);
  })
  .catch(err => {
    console.log(err);
  });
